package com.cf.compent.rank.impl;

import com.cf.compent.rank.*;
import com.cf.core.player.UserInfo;
import com.cf.game.service.constants.EnumReturnCode;
import com.cf.game.service.exception.BizException;
import com.cf.game.service.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.Tuple;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * game-server-RedisRankService
 *
 * @author <a href="2428922347@qq.com">Zhu mingming</a>
 * @info
 * @since 2018/5/10 下午 03:28
 */
@Slf4j
public class RedisRankService implements RankService {

    @Autowired
    private JedisCluster jedisCluster;

    @Autowired
    private UserKeyFormatter userKeyFormater;

    @Override
    public UserRank rankUserScore(String rankKey, UserScore userScore) {
        String userKey = userKeyFormater.encodeUserKey(userScore.getUserId());
        if (!StringUtils.hasLength(rankKey) || !StringUtils.hasLength(userKey))
            throw new BizException(EnumReturnCode.ERROR.getCode(), "排行榜KEY缺失！");
        if (StringUtils.hasLength(userKey)) {
            Double targetScore = getScore(rankKey, userKey);
            if (targetScore == null)
                targetScore = 0d;
            if (userScore.getScore() > targetScore) {
                log.info("添加用户【{}】新的高分【{}】，原先得分【{}】", userKey, userScore.getScore(), rankKey);
                jedisCluster.zadd(rankKey, userScore.getScore(), userKey);
            } else {
                log.info("当前用户【{}】分数太低【{}】，此次分数不参与排名了", userKey, userScore.getScore());
            }
        }
        return this.userRank(rankKey, userKey);
    }

    /**
     * 获取排行数据内部方法
     *
     * @param rankKey
     * @param start
     * @param end
     * @param filter
     * @return
     */
    public List<UserRank> rank(String rankKey, int start, int end, RankFilter filter, boolean z) {
        Set<Tuple> tuples = z ? jedisCluster.zrevrangeWithScores(rankKey, start, end) : jedisCluster.zrangeByScoreWithScores(rankKey, start, end);
        List<UserRank> userRanks = new ArrayList<>();
        if (tuples == null || tuples.size() == 0)
            return Collections.emptyList();

        AtomicReference<Integer> index = new AtomicReference<>(0);
        tuples.forEach(tuple -> {
            if (!filter.filter(tuple.getElement())) {
                log.info("当前用户【{}】不需要参与排行榜！", tuple.getElement());
                return;
            }
            Integer indexValue = index.getAndSet(index.get() + 1);
            DefaultUserRank rank = toUserRank(tuple, indexValue);
            userRanks.add(rank);

        });

        return userRanks;
    }

    private DefaultUserRank toUserRank(Tuple tuple, Integer indexValue) {
        UserInfo userInfo = userKeyFormater.decodeUserInfo(tuple.getElement());
        return new DefaultUserRank(indexValue, tuple.getScore(), userInfo.getName(), userInfo.getHead(), userInfo.getUserId() + "");
    }

    @Override
    public List<UserRank> top(String rankKey, int num, RankFilter filter) {
        return rank(rankKey, 0, num, filter, true);
    }

    @Override
    public List<UserRank> reciprocal(String rankKey, int num, RankFilter filter) {
        return rank(rankKey, 0, num, filter, false);
    }

    @Override
    public UserRank userRank(String rankKey, String userId) {
        String userKey = userKeyFormater.encodeUserKey(userId);
        Long rank = jedisCluster.zrevrank(rankKey, userKey);
        Double score = jedisCluster.zscore(rankKey, userKey);
        return toUserRank(new Tuple(userKey, score), rank.intValue());
    }


    public Double getScore(String rankKey, String userKey) {
        log.info("开始获取【{}】在游戏【{}】的得分", userKey, rankKey);
        Double score = jedisCluster.zscore(rankKey, userKey);
        log.info("开始获取【{}】在游戏【{}】的得分", userKey, rankKey);
        return score;
    }
}
